package com.company.Utils;


import com.company.Lab3.AditiveMethod;

import java.util.Scanner;

public class MatrixUtils {
    static Scanner scanner = new Scanner(System.in);

    private static void minFromRow(double[][] matrix, int r, int c, double[] rmin) {
        for (int i = 0; i < r; i++) {
            double min = matrix[i][0];
            for (int j = 0; j < c; j++) {
                min = Math.min(min, matrix[i][j]);
            }
            rmin[i] = min;
        }
    }

    private static void minFromColumn(double[][] matrix, int r, int c, double[] cmin) {
        for (int i = 0; i < c; i++) {
            double min = matrix[0][i];
            for (int j = 0; j < r; j++) {
                min = Math.min(min, matrix[j][i]);
            }
            cmin[i] = min;
        }
    }

    private static void maxFromColumn(double[][] matrix, int r, int c, double[] cmax) {
        for (int i = 0; i < c; i++) {
            double max = matrix[0][i];
            for (int j = 0; j < r; j++) {
                max = Math.max(max, matrix[j][i]);
            }
            cmax[i] = max;
        }
    }

    private static void maxFromRow(double[][] matrix, int r, int c, double[] rmax) {
        for (int i = 0; i < r; i++) {
            double max = matrix[i][0];
            for (int j = 0; j < c; j++) {
                max = Math.max(max, matrix[i][j]);
            }
            rmax[i] = max;
        }
    }

    public static void readMatrixSize(int r, int c, double alpha, String[] priority) {
        System.out.println("Introduceti numarul de randuri :");
        r = scanner.nextInt();
        System.out.println("Introduceti numarul de coloane :");
        c = scanner.nextInt();
        System.out.println("Intoruceti valoarea coeficientului alpha :");
        alpha = scanner.nextDouble();
        priority = new String[c];
        System.out.println("Introduceti priotitatea : ");
        for (int i = 0; i < c; i++) {
            System.out.print("Prioritatea [" + i + "] : ");
            if (i == 0) {
                scanner.nextLine();
            }
            priority[i] = scanner.nextLine();
        }
    }

    public static double[][] readMatrix(final int r, final int c) {
        double[][] initMatrix = new double[r][c];
        System.out.println("Introduceti elementele matricii : ");
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                System.out.print("[" + i + "][" + j + "] : ");
                initMatrix[i][j] = scanner.nextDouble();
            }
        }
        return initMatrix;
    }


    public static void displayMatrix(final double[][] matrix, final int r, final int c) {
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                System.out.print(matrix[i][j] + "\t");
            }
            System.out.println();
        }
    }

    public static double getOptimist(final double[][] matrix, final int r, final int c) {
        double[] rmax = new double[r];
        maxFromRow(matrix, r, c, rmax);
        double maximax = rmax[0];
        for (double v : rmax) {
            maximax = Math.max(maximax, v);
        }
        return maximax;
    }

    public static double getPessimist(final double[][] matrix, final int r, final int c) {
        double[] rmin = new double[r];
        minFromRow(matrix, r, c, rmin);
        double minmax = rmin[0];
        for (double v : rmin) {
            minmax = Math.max(minmax, v);
        }
        return minmax;
    }

    public static double getRealist(final double[][] matrix, final int r, final int c, final double alpha) {
        double[] rmax = new double[r];
        double[] rmin = new double[r];
        double[] result = new double[r];
        double maxR;
        maxFromRow(matrix, r, c, rmax);
        minFromRow(matrix, r, c, rmin);
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                result[i] = (alpha * rmax[i]) + ((1 - alpha) * rmin[i]);
            }
        }
        maxR = result[0];
        for (double v : result) {
            maxR = Math.max(maxR, v);
        }
        return maxR;
    }

    public static double getRegret(final double[][] matrix, final int r, final int c) {
        double[] cmax = new double[c];
        double[][] substract = new double[r][c];
        double[] smax = new double[r];
        maxFromColumn(matrix, r, c, cmax);
        for (int i = 0; i < c; i++) {
            for (int j = 0; j < r; j++) {
                substract[j][i] = cmax[i] - matrix[j][i];
            }
        }
        maxFromRow(substract, r, c, smax);
        double min = smax[0];
        for (double v : smax) {
            min = Math.min(min, v);
        }
        return min;
    }

    public static double getEchiprob(final double[][] matrix, final int r, final int c) {
        double[] sum = new double[r];
        double coefficient = (double) 1 / c;
        for (int i = 0; i < r; i++) {
            sum[i] = 0;
            for (int j = 0; j < c; j++) {
                sum[i] = sum[i] + matrix[i][j];
            }
            sum[i] *= coefficient;
        }
        double max = sum[0];
        for (double v : sum) {
            max = Math.max(max, v);
        }
        return max;
    }

    public static double[][] getUtility(final double[][] matrix, final int r, final int c, final String[] priority) {
        double[][] utilityMatrix;
        double[] maxValuesOnColumn = new double[c];
        double[] minValuesOnColumn = new double[c];
        maxFromColumn(matrix, r, c, maxValuesOnColumn);
        minFromColumn(matrix, r, c, minValuesOnColumn);
        utilityMatrix = calcUtilityMatrix(matrix, maxValuesOnColumn, minValuesOnColumn, priority, r, c);
        return utilityMatrix;
    }


    private static double[][] calcUtilityMatrix(final double[][] main, final double[] maxValuesOnColumn
            , final double[] minValuesOnColumn, final String[] priority, final int r, final int c) {
        double[][] utility = new double[r][c];
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (priority[j].equalsIgnoreCase("min")) {
                    utility[i][j] = (maxValuesOnColumn[j] - main[i][j]) / (maxValuesOnColumn[j] - minValuesOnColumn[j]);
                } else if (priority[j].equalsIgnoreCase("max")) {
                    utility[i][j] = (main[i][j] - minValuesOnColumn[j]) / (maxValuesOnColumn[j] - minValuesOnColumn[j]);
                }
            }
        }
        return utility;
    }

    public static double[][] calcGrDepartare(final double[][] mainMatrix, final String[] priority, final int r, final int c) {
        double[][] distance = new double[r][c];
        double[] maxValuesOnColumn = AditiveMethod.calcMaxOnColumn(mainMatrix, r, c);
        double[] minValuesOnColumn = AditiveMethod.calcMinOnColumn(mainMatrix, r, c);

        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (priority[j].equalsIgnoreCase("min")) {
                    distance[i][j] = (mainMatrix[i][j] - minValuesOnColumn[j]) / mainMatrix[i][j];
                } else if (priority[j].equalsIgnoreCase("max")) {
                    distance[i][j] = (maxValuesOnColumn[j] - mainMatrix[i][j]) / maxValuesOnColumn[j];
                }
            }
        }
        return distance;
    }

    public static double[][] calcXMatrix(final double[][] distanceMatrix, final double[] alpha, final int r, final int c) {
        double[][] xMatrix = new double[r][c];
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                xMatrix[i][j] = distanceMatrix[i][j] * alpha[j];
            }
        }
        return xMatrix;
    }

    public static double[][] calcBelogingMatrix(final double[][] xMatrix, final double exponent, final String[] priority, final int r, final int c) {
        double[][] belogingMatrix = new double[r][c];
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (priority[j].equalsIgnoreCase("max")) {
                    belogingMatrix[i][j] = Math.pow(exponent, xMatrix[i][j]);
                } else if (priority[j].equalsIgnoreCase("min")) {
                    belogingMatrix[i][j] = Math.pow(exponent, -xMatrix[i][j]);
                }
            }
        }
        return belogingMatrix;
    }


}
